#! /usr/bin/env python
# coding=utf-8
# ******************************************************************************
# Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
# licensed under the Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#     http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
# PURPOSE.
# See the Mulan PSL v2 for more details.
# Author: senlin
# Create: 2021-04-22
# ******************************************************************************/

import argparse
import os, sys
import re
import logging
import csv, codecs
import logger
from itertools import islice

CURRENT_PATH = os.path.dirname(os.path.abspath(__file__))
srpmnames = []
pkgnames = []

logger = logger.init("oepkgs")  # 获取一个日志对象，这里参数 只有模块名

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("-m", "--model", default=None, nargs="?", 
                        help=" process the oepkg*.csv: Exact matching -> 'ex' or Fuzzy matching -> 'fu' ")

    parser.add_argument("-e", "--oepkg_list", default=None, nargs="?",
                        help="choose the srpm list from oepkgs.")

    parser.add_argument("-o", "--package_list", default=None, nargs="?", 
                        help=" choose the package list form new feature")

    parser.add_argument("-s", "--process_csv", default=None, nargs="?", 
                        help=" process the oepkg*.csv: Split cell into cells ")

    args = parser.parse_args()

    if args.oepkg_list and args.package_list:
        process(args)
    elif args.process_csv:
        process_src_csv(args.model, args.process_csv)
    
def process_src_csv(model, csv_file):
    """
    Split the string to get the SRPM packet information.
    For example, 
    场景1："389-ds-base-1.3.10.2-6.src.rpm     13-Apr-2021 15:13   3702075" -> "389-ds-base-1.3.10.2-6.src.rpm"
    场景2："389-ds-base.src   1.3.10.2-6  centos7-centos" -> "389-ds-base" "1.3.10.2" "centos7-centos"
    场景3："2ping 3.2.1" -> "2ping" "3.2.1"
    """
    conf_dir = os.path.dirname(os.path.abspath(__file__))
    conf_path = os.path.join(conf_dir, csv_file)
    if not os.path.isfile(conf_path):
        logger.warning("not found the config file: %s", conf_path)
        return False

    data = []
    line_num = 0

    if model == '1': 
        with open (conf_path,'r',encoding='gbk') as conf_file:
            reader = csv.reader(conf_file)
            for line in islice(reader, 1, None):
                logger.info("oepkg srpm info: %s", line[0])
                
                data.append([])
                srpm, otherinfo = line[0].split(" ", 1)

                data[line_num].append(srpm.strip())
                #data[line_num].append(otherinfo.strip())
                line_num += 1

        result_file_name = 'split_' + csv_file
        with codecs.open(result_file_name,'w','gbk') as result_file:
            writer = csv.writer(result_file)
            writer.writerow(["option", "desc"])
            for line in data:
                writer.writerow(line)

    if model == '2': 
        with open (conf_path,'r') as conf_file:
            reader = csv.reader(conf_file)
            for line in reader:
                logger.info("oepkg srpm info: %s", line[0]) 
                data.append([])
                temp_line = ' '.join(line[0].split())
                srpm, version, path = temp_line.split(" ", 2)
                # temp_line=' '.join(filter(lambda x: x, line[0].split(' ')))
                logger.info("srpm: %s, version: %s, path: %s", srpm, version, path) 
                #srpm, version, path = ''.join(temp_line.split())

                data[line_num].append(srpm.strip())
                data[line_num].append(version.strip())
                data[line_num].append(path.strip())
                line_num += 1

        result_file_name = 'split_' + csv_file
        with open(result_file_name,'w') as result_file:
            writer = csv.writer(result_file)
            writer.writerow(["NAME", "VERSION", "DIR"])
            for line in data:
                writer.writerow(line)

    if model == '3': 
        with open (conf_path,'r') as conf_file:
            reader = csv.reader(conf_file)
            for line in reader:
                logger.info("srpm info: %s, project: %s", line[0], line[1])
                data.append([])
                srpm, version = line[0].split(" ", 1)
                logger.info("srpm: %s, version: %s, path: %s", srpm, version, line[1]) 
                data[line_num].append(srpm.strip())
                data[line_num].append(version.strip())
                data[line_num].append(line[1].strip())
                line_num += 1

        result_file_name = 'split_' + csv_file
        with open(result_file_name,'w') as result_file:
            writer = csv.writer(result_file)
            writer.writerow(["NAME", "VERSION", "project"])
            for line in data:
                writer.writerow(line)

    logger.info("process split oepkgs.csv end!")
    

def process(args):
    """ Preparation and processing of the main entrance."""

    add_file_output(logger)

    package_list = args.package_list
    oepkg_list = args.oepkg_list
    if args.model == 'ex': # 精确匹配：name-version
        result_file_name = 'result_exact_' + oepkg_list
    if args.model == 'fu': # 模糊匹配：name-version
        result_file_name = 'result_fuzzy_' + oepkg_list

    logger.warning("pkgname_file:%s, srpm_file:%s, result: %s", package_list, oepkg_list, result_file_name)

    if args.model == 'ex':
        exact_match(package_list, oepkg_list, result_file_name)

    if args.model == 'fu':
        fuzzy_match(package_list, oepkg_list, result_file_name)

    return True
    

def exact_match(package_list, oepkg_list, result_file_name):
    """
    基于name-version精确查找
    """
    load_pkginfo_list_csv(pkgnames, package_list) # 二维列表{包名， 版本号}
    load_oepkg_srpm_list_csv(srpmnames, oepkg_list) # 三维列表{srpm包名， 版本号，目录}

    
    with codecs.open(result_file_name,'w','gbk') as result_file:
        writer = csv.writer(result_file)
        writer.writerow(["包名", "版本号", "目录"])

        for x in pkgnames:
            num = 0 #初始化计数变量
            match_flag = False
            pkginfo = []
            pkginfo.append('-'.join(x))
            result_data = []
            for y in srpmnames: # 精确匹配：name-version
                if y[0]==x[0] and whole_word_match(y[1], x[1]):
                    num += 1
                    match_flag = True
                    result_data.append(x[0])
                    result_data.append(x[1])
                    result_data.append(y[2])
                    logger.info("find :%s at line:%s", x, y)
                    break
            if match_flag == True:
                writer.writerow(result_data)
            else:
                result_data.append(x[0])
                result_data.append(x[1])
                result_data.append('NA')
                writer.writerow(result_data)

    logger.info("process compare pkglist with oepkgs end!")

def fuzzy_match(package_list, oepkg_list, result_file_name):
    """
    基于name***version模糊查找
    """
    load_pkginfo_list_csv(pkgnames, package_list) # 二维列表{包名， 版本号}
    load_oepkg_srpm_list_csv(srpmnames, oepkg_list) # 二维列表{srpm包名， 目录}

    
    with codecs.open(result_file_name,'w','gbk') as result_file:
        writer = csv.writer(result_file)
        writer.writerow(["Name-feature", "version-SP2", "Name-SP2","version-SP2", "Project"])

        for x in pkgnames:
            num = 0 #初始化计数变量
            match_flag = False
            pkginfo = []
            pkginfo.append(x[0])
            result_data = []
            for y in srpmnames:
                # 模糊匹配: name***version
                
                if x[0] in y[0]:
                    num += 1
                    match_flag = True
                    result_data.append(x[0])
                    result_data.append(x[1])
                    result_data.append(y[0])
                    result_data.append(y[1])
                    result_data.append(y[2])
                    writer.writerow(result_data)
                    logger.info("find :%s at line:%s", x, y)
                    
            if match_flag == False:
                result_data.append(x[0])
                result_data.append(x[1])
                result_data.append('NA')
                result_data.append('NA')
                result_data.append('NA')
                writer.writerow(result_data)

    logger.info("process compare pkglist with oepkgs end!")


def whole_word_match(detailinfo, keyword_list):
    """
    判断输入的字符串中是否有关键字（做全字匹配，例如关键字为scanf则不匹配sscanf）
        如果匹配到了，返回1，没有返回0
    """

    logger.info("detailinfo: %s, keyword_list: %s", detailinfo, keyword_list) # 
    for tmp_keyword in keyword_list:
        #正则表达查询性能较差，先用find函数过滤，因为大部分字符串都不需要走正则查询
        if  -1 != detailinfo.find(tmp_keyword):
            # 匹配^tmp_keyword$;
            # 匹配^tmp_keyword(非字母数字下划线)(任意字符);
            # 匹配(任意字符)(非字母数字下划线)tmp_keyword$;
            # 匹配(任意字符)(非字母数字下划线)tmp_keyword(非字母数字下划线)(任意字符)
            pattern_str=r'(^'+tmp_keyword+'$)|(^'+tmp_keyword+'(\W+).*)|(.*(\W+)'+tmp_keyword+'$)|(.*(\W+)'+tmp_keyword+'(\W+).*)'.format(tmp_keyword=tmp_keyword)
            if re.match(r''+pattern_str+'', detailinfo):
                logger.info("get pkg-version({}) from srpm({})".format(tmp_keyword, detailinfo))
                return True
    return False

def load_oepkg_srpm_list_csv(words, filename):
    """
    从关键词文件中导入关键词至keywords全局变量
    :return: num of keywords
    """
    conf_dir = os.path.dirname(os.path.abspath(__file__))
    conf_path = os.path.join(conf_dir, filename)
    if not os.path.isfile(conf_path):
        logger.warning("not found the config file: %s", conf_path)
        return False

    line_num = 0

    with open (conf_path,'r',encoding='gbk') as conf_file:
        reader = csv.reader(conf_file)
        for line in islice(reader, 1, None):
            logger.info("oepkg srpm info: %s, version: %s, dir: %s", line[0], line[1], line[2]) # line[0] 是srpm信息，line[1]是目录
            words.append([])
            #srpm, otherinfo = line[0].split(" ", 1)
            words[line_num].append(line[0].strip().replace('+', 'x'))
            words[line_num].append(line[1].strip())
            words[line_num].append(line[2].strip())
            line_num += 1
    return True

def load_pkginfo_list_csv(words, filename):
    """
    从关键词文件中导入关键词至keywords全局变量
    :return: num of keywords
    """
    conf_dir = os.path.dirname(os.path.abspath(__file__))
    conf_path = os.path.join(conf_dir, filename)
    if not os.path.isfile(conf_path):
        logger.warning("not found the config file: %s", conf_path)
        return False
    line_num = 0
    with open (conf_path,'r',encoding='gbk') as conf_file:
        reader = csv.reader(conf_file)
        for line in islice(reader, 1, None):
            words.append([])
            logger.info("pkgname: %s, version: %s", line[0], line[1])
            words[line_num].append(line[0].strip().replace('+', 'x'))
            words[line_num].append(line[1].strip())
            line_num += 1
    return True

def add_file_output(log):
    """
    Args:
        log: 日志对象
    Returns: 添加文件输出流的日志对象
    """
    log.log_name = "compare_oepkg.log"
    log_file_name = os.path.join(CURRENT_PATH, "compare_oepkg.log")
    with open(log_file_name, "w+") as file:
        file.truncate()  # 清空原来的内容
    file_handler = logging.FileHandler(log_file_name)
    file_handler.setLevel(logger.LEVEL)
    file_handler.setFormatter(logger.FORMATTER)
    log.handlers = []
    log.addHandler(file_handler)


if __name__ == '__main__':
    main()